#include "Grammar.h"

//This is the class where the accepted speech commands are defined. Used by the voice recognizer.
//This class accepts an ISpRecoGrammar which will then be modified such that the here-defined commands are accepted.


#define tolerance 9 //Defines, how tolerant the system behaves. The higher the number, the more phrases are accepted, but the more frequently false positives occur.
#define confidence 0 //Defines, how confident the rule must be accepted. Can be either 0 or 1. If set to 1, only phrases the system is certain of having understood are treated.
					 //Otherwise, also "potential matches" are treated as commands.


//The following section gives an overview of the accepted commands.

//Grabbing
//========
//Tolerance 0:	Grab
//Tolerance >5:	Grab
//				Take
//
//
//Releasing
//=========
//Tolerance 0:	Go
//Tolerance >5:	Release
//				Throw
//				Go
//
//Setting
//=========
//Tolerance 0:	Set
//Tolerance >5:	Set
//				Put
//
//
//Start game
//==========
//Tolerance 0:	Start
//Tolerance >3:	Start
//				Start (new) Game
//Tolerance >5:	Start
//				[Start| Launch] (new) Game
//Tolerance >7:	(Please) Start
//				(Please) [Start| Launch| Set up] (new) [Game| Play]
//				
//Stop game
//=========
//Tolerance 0:	[Exit| Quit]
//Tolerance >3:	[Exit| Quit]
//				[Exit| Quit] Game
//Tolerance >5:	[Exit| Quit]
//				[Exit| Quit| Abort] Game
//Tolerance >7:	(Please) [Exit| Quit]
//				(Please) [Exit| Quit| Abort] [Game| Play]
//				
//				
//Pause game
//==========
//Tolerance 0:	Pause
//Tolerance >3:	Pause
//				Pause Game
//Tolerance >5:	[Interrupt| Pause]
//				[Interrupt| Pause] Game
//Tolerance >7:	(Please)[Interrupt| Pause](the) [Game| Play]
//
//Resume game
//==========
//Tolerance 0:	Resume
//Tolerance >3:	[Resume| Continue]
//				[Resume| Continue] Game
//Tolerance >5:	[Resume| Continue]
//				[Resume| Continue] Game
//Tolerance >7:	(Please)[Resume| Continue](the) [Game| Play]
//
//Reset game
//==========
//Tolerance 0:	Reset
//Tolerance >3:	[Reset| Relaunch]
//				[Reset| Relaunch] Game
//Tolerance >5:	[Reset| Relaunch]
//				[Reset| Relaunch] Game
//Tolerance >7:	(Please)[Reset| Relaunch](the) [Game| Play]
//
//Confirm
//=======
//Tolerance 0:	Confirm
//Tolerance >3:	[Confirm| Yes]
//Tolerance >5:	[Confirm| Yes| Affirm]
//
//
//Cancel
//=======
//Tolerance 0:	Cancel
//Tolerance >3:	[Cancel| No]
//Tolerance >5:	[Cancel| No| Stop]


//The constructor
Grammar::Grammar(CComPtr<ISpRecoGrammar> cpGram){
	this->cpGram=cpGram;
}

//Distructor: free memory
Grammar::~Grammar(void){
	free(cpGram);
}


//Get the confidence level: called by voice recognizer
int Grammar::getConfidence(void){
	return confidence;
}


//Initialise the grammar, i.e. define the phrases and rules
void Grammar::init(void){
	//this->defineDirections(); //Not used
	//this->defineStart(); // Not used
	//this->defineStop(); // Not used
	this->defineReset();
	//this->definePause(); // Not used
	//this->defineResume(); // Not used
	this->defineConfirm();
	this->defineRunTimeCommands();
}

//Define the accepted commands for grabbing an object and releasing it, plus to set a grabbed object
void Grammar::defineRunTimeCommands(void){
	//Grabbing
	hr = cpGram->GetRule(L"GRAB", RULE_RUNTIME_GRAB, SPRAF_TopLevel | SPRAF_Active, TRUE, &hRunTimeCommands);
	hr = cpGram->AddWordTransition(hRunTimeCommands, NULL, L"Grab", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>5)
	hr = cpGram->AddWordTransition(hRunTimeCommands, NULL, L"Take", L" ", SPWT_LEXICAL, 1, NULL);
	
	//Releasing
	hr = cpGram->GetRule(L"GO", RULE_RUNTIME_GO, SPRAF_TopLevel | SPRAF_Active, TRUE, &hRunTimeCommands);
	if(tolerance>5)
	hr = cpGram->AddWordTransition(hRunTimeCommands, NULL, L"Release", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>5)
	hr = cpGram->AddWordTransition(hRunTimeCommands, NULL, L"Throw", L" ", SPWT_LEXICAL, 1, NULL);
	hr = cpGram->AddWordTransition(hRunTimeCommands, NULL, L"Go", L" ", SPWT_LEXICAL, 1, NULL);

	//Putting
	hr = cpGram->GetRule(L"SET", RULE_RUNTIME_SET, SPRAF_TopLevel | SPRAF_Active, TRUE, &hRunTimeCommands);
	if(tolerance>5)
	hr = cpGram->AddWordTransition(hRunTimeCommands, NULL, L"Put", L" ", SPWT_LEXICAL, 1, NULL);
	hr = cpGram->AddWordTransition(hRunTimeCommands, NULL, L"Set", L" ", SPWT_LEXICAL, 1, NULL);
}

//Define the accepted commands for launching the game
void Grammar::defineStart(void){
	hr = cpGram->GetRule(L"START", RULE_START_GAME, SPRAF_TopLevel | SPRAF_Active, TRUE, &hStartGame_First);
	hr = cpGram->CreateNewState(hStartGame_First, &hStartGame_Second);

	//Optional
	if(tolerance>7)
	hr = cpGram->AddWordTransition(hStartGame_First, hStartGame_First, L"Please", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>3)
	hr = cpGram->AddWordTransition(hStartGame_First, hStartGame_Second, L"Start", L" ", SPWT_LEXICAL, 1, NULL);
	hr = cpGram->AddWordTransition(hStartGame_First, NULL, L"Start", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>5)
	hr = cpGram->AddWordTransition(hStartGame_First, hStartGame_Second, L"Launch", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>7)
	hr = cpGram->AddWordTransition(hStartGame_First, hStartGame_Second, L"Set up", L" ", SPWT_LEXICAL, 1, NULL);

	//Optional
	if(tolerance>3)
	hr = cpGram->AddWordTransition(hStartGame_Second, hStartGame_Second, L"New", L" ", SPWT_LEXICAL, 1, NULL);

	if(tolerance>3)
	hr = cpGram->AddWordTransition(hStartGame_Second, NULL, L"Game", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>7)
	hr = cpGram->AddWordTransition(hStartGame_Second, NULL, L"Play", L" ", SPWT_LEXICAL, 1, NULL);
}

//Define the accepted commands for stopping the game
void Grammar::defineStop(void){
	hr = cpGram->GetRule(L"STOP", RULE_STOP_GAME, SPRAF_TopLevel | SPRAF_Active, TRUE, &hStopGame_First);
	if(tolerance>3)
	hr = cpGram->CreateNewState(hStopGame_First, &hStopGame_Second);

	//Optional
	if(tolerance>7)
	hr=cpGram->AddWordTransition(hStopGame_First, hStopGame_First, L"Please", L" ", SPWT_LEXICAL, 1, NULL);

	if(tolerance>3){
	hr=cpGram->AddWordTransition(hStopGame_First, hStopGame_Second, L"Exit", L" ", SPWT_LEXICAL, 1, NULL);
	hr=cpGram->AddWordTransition(hStopGame_First, hStopGame_Second, L"Quit", L" ", SPWT_LEXICAL, 1, NULL);
	}
	hr=cpGram->AddWordTransition(hStopGame_First, NULL, L"Exit", L" ", SPWT_LEXICAL, 1, NULL);
	hr=cpGram->AddWordTransition(hStopGame_First, NULL, L"Quit", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>5)
	hr=cpGram->AddWordTransition(hStopGame_First, hStopGame_Second, L"Abort", L" ", SPWT_LEXICAL, 1, NULL);

	
	if(tolerance>3)
	hr=cpGram->AddWordTransition(hStopGame_Second, NULL, L"Game", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>7)
	hr=cpGram->AddWordTransition(hStopGame_Second, NULL, L"Play", L" ", SPWT_LEXICAL, 1, NULL);
}

//Define the accepted commands for pausing the game
void Grammar::definePause(void){
	hr = cpGram->GetRule(L"PAUSE", RULE_PAUSE_GAME, SPRAF_TopLevel | SPRAF_Active, TRUE, &hPauseGame_First);
	if(tolerance>3)
	hr = cpGram->CreateNewState(hPauseGame_First, &hPauseGame_Second);

	//Optional
	if(tolerance>7)
	hr=cpGram->AddWordTransition(hPauseGame_First, hPauseGame_First, L"Please", L" ", SPWT_LEXICAL, 1, NULL);

	if(tolerance>5){
	hr=cpGram->AddWordTransition(hPauseGame_First, hPauseGame_Second, L"Interrupt", L" ", SPWT_LEXICAL, 1, NULL);
	hr=cpGram->AddWordTransition(hPauseGame_First, hPauseGame_Second, L"Pause", L" ", SPWT_LEXICAL, 1, NULL);
	}
	if(tolerance>5)
	hr=cpGram->AddWordTransition(hPauseGame_First, NULL, L"Interrupt", L" ", SPWT_LEXICAL, 1, NULL);
	hr=cpGram->AddWordTransition(hPauseGame_First, NULL, L"Pause", L" ", SPWT_LEXICAL, 1, NULL);

	//Optional
	if(tolerance>7)
	hr = cpGram->AddWordTransition(hPauseGame_Second, hPauseGame_Second, L"the", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>3)
	hr=cpGram->AddWordTransition(hPauseGame_Second, NULL, L"Game", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>7)
	hr=cpGram->AddWordTransition(hPauseGame_Second, NULL, L"Play", L" ", SPWT_LEXICAL, 1, NULL);
}

//Define the accepted commands for resuming the game
void Grammar::defineResume(void){
	hr = cpGram->GetRule(L"RESUME", RULE_RESUME_GAME, SPRAF_TopLevel | SPRAF_Active, TRUE, &hResumeGame_First);
	if(tolerance>3)
	hr = cpGram->CreateNewState(hResumeGame_First, &hResumeGame_Second);
	
	//Optional
	if(tolerance>7)
	hr=cpGram->AddWordTransition(hResumeGame_First, hResumeGame_First, L"Please", L" ", SPWT_LEXICAL, 1, NULL);

	
	if(tolerance>3){
	hr=cpGram->AddWordTransition(hResumeGame_First, hResumeGame_Second, L"Continue", L" ", SPWT_LEXICAL, 1, NULL);
	hr=cpGram->AddWordTransition(hResumeGame_First, hResumeGame_Second, L"Resume", L" ", SPWT_LEXICAL, 1, NULL);
	}
	if(tolerance>3)
	hr=cpGram->AddWordTransition(hResumeGame_First, NULL, L"Continue", L" ", SPWT_LEXICAL, 1, NULL);
	hr=cpGram->AddWordTransition(hResumeGame_First, NULL, L"Resume", L" ", SPWT_LEXICAL, 1, NULL);

	//Optional
	if(tolerance>7)
	hr = cpGram->AddWordTransition(hResumeGame_Second, hResumeGame_Second, L"the", L" ", SPWT_LEXICAL, 1, NULL);

	if(tolerance>3)
	hr=cpGram->AddWordTransition(hResumeGame_Second, NULL, L"Game", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>7)
	hr=cpGram->AddWordTransition(hResumeGame_Second, NULL, L"Play", L" ", SPWT_LEXICAL, 1, NULL);
}


//Define the accepted commands for resetting the game
void Grammar::defineReset(void){
	hr = cpGram->GetRule(L"RESET", RULE_RESET_GAME, SPRAF_TopLevel | SPRAF_Active, TRUE, &hResetGame_First);
	if(tolerance>3)
	hr = cpGram->CreateNewState(hResetGame_First, &hResetGame_Second);

	//Optional
	if(tolerance>7)
	hr=cpGram->AddWordTransition(hResetGame_First, hResetGame_First, L"Please", L" ", SPWT_LEXICAL, 1, NULL);
	
	if(tolerance>3){
	hr=cpGram->AddWordTransition(hResetGame_First, hResetGame_Second, L"Relaunch", L" ", SPWT_LEXICAL, 1, NULL);
	hr=cpGram->AddWordTransition(hResetGame_First, hResetGame_Second, L"Reset", L" ", SPWT_LEXICAL, 1, NULL);
	hr=cpGram->AddWordTransition(hResetGame_First, NULL, L"Relaunch", L" ", SPWT_LEXICAL, 1, NULL);
	}
	
	hr=cpGram->AddWordTransition(hResetGame_First, NULL, L"Reset", L" ", SPWT_LEXICAL, 1, NULL);

	//Optional
	if(tolerance>7)
	hr = cpGram->AddWordTransition(hResetGame_Second, hResetGame_Second, L"the", L" ", SPWT_LEXICAL, 1, NULL);

	if(tolerance>3)
	hr=cpGram->AddWordTransition(hResetGame_Second, NULL, L"Game", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>7)
	hr=cpGram->AddWordTransition(hResetGame_Second, NULL, L"Play", L" ", SPWT_LEXICAL, 1, NULL);
}

//Define the accepted commands for indicating directions. Not yet used in the game, but can be activated for a future game release
void Grammar::defineDirections(void){
	hr = cpGram->GetRule(L"Up", RULE_DIRECTION_UP, SPRAF_TopLevel | SPRAF_Active, TRUE, &hDirection);
	hr = cpGram->AddWordTransition(hDirection, NULL, L"Up", L" ", SPWT_LEXICAL, 1, NULL);

	hr = cpGram->GetRule(L"Down", RULE_DIRECTION_DOWN, SPRAF_TopLevel | SPRAF_Active, TRUE, &hDirection);
	hr = cpGram->AddWordTransition(hDirection, NULL, L"Down", L" ", SPWT_LEXICAL, 1, NULL);

	hr = cpGram->GetRule(L"Left", RULE_DIRECTION_LEFT, SPRAF_TopLevel | SPRAF_Active, TRUE, &hDirection);
	hr = cpGram->AddWordTransition(hDirection, NULL, L"Left", L" ", SPWT_LEXICAL, 1, NULL);

	hr = cpGram->GetRule(L"Right", RULE_DIRECTION_RIGHT, SPRAF_TopLevel | SPRAF_Active, TRUE, &hDirection);
	hr = cpGram->AddWordTransition(hDirection, NULL, L"Right", L" ", SPWT_LEXICAL, 1, NULL);
}

//Define the accepted phrase to confirm or cancel a command
void Grammar::defineConfirm(void){
	//Confirm
	hr = cpGram->GetRule(L"Confirm", RULE_CONFIRM, SPRAF_TopLevel | SPRAF_Active, TRUE, &hConfirm);
	hr = cpGram->AddWordTransition(hConfirm, NULL, L"Confirm", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>3)
	hr = cpGram->AddWordTransition(hConfirm, NULL, L"Yes", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>5)
	hr = cpGram->AddWordTransition(hConfirm, NULL, L"Affirm", L" ", SPWT_LEXICAL, 1, NULL);

	//Cancel
	hr = cpGram->GetRule(L"Cancel", RULE_CANCEL, SPRAF_TopLevel | SPRAF_Active, TRUE, &hCancel);
	hr = cpGram->AddWordTransition(hCancel, NULL, L"Cancel", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>3)
	hr = cpGram->AddWordTransition(hCancel, NULL, L"No", L" ", SPWT_LEXICAL, 1, NULL);
	if(tolerance>5)
	hr = cpGram->AddWordTransition(hCancel, NULL, L"Stop", L" ", SPWT_LEXICAL, 1, NULL);
}

